use std::{rc::Rc, cell::RefCell};

use crate::{rtda::Frame, instructions::base::{BytecodeReader, Instruction}};

// astore指令的索引来自操作数，其他来自指令
// Store reference into local variable
#[derive(Debug, Default)]
pub struct ASTORE {
    index: usize
}

impl Instruction for ASTORE {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.index = reader.read_u8() as usize;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _astore(frame, self.index);
    }
}

impl ASTORE {
    pub fn set_index(&mut self, index: usize) {
        self.index = index;
    } 
}

#[derive(Debug, Default)]
pub struct ASTORE_0 { }

impl Instruction for ASTORE_0 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _astore(frame, 0);
    }
}

#[derive(Debug, Default)]
pub struct ASTORE_1 { }

impl Instruction for ASTORE_1 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _astore(frame, 1);
    }
}

#[derive(Debug, Default)]
pub struct ASTORE_2 { }

impl Instruction for ASTORE_2 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _astore(frame, 2);
    }
}

#[derive(Debug, Default)]
pub struct ASTORE_3 { }

impl Instruction for ASTORE_3 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _astore(frame, 3);
    }
}


// 通用加载，把变量从操作数栈顶弹出，存入局部变量表。
fn _astore(frame: Rc<RefCell<Frame>>, index: usize) {
    let val = frame.borrow().get_operand_stack().borrow_mut().pop_ref();
    frame.borrow().get_local_vars().borrow_mut().set_ref(index, val);
}